package me.zhengjie.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.common.Result;
import me.zhengjie.dto.*;
import me.zhengjie.entity.TaskList;
import me.zhengjie.entity.TrafficCtlArea;
import me.zhengjie.observer.caster.WcsMulticaster;
import me.zhengjie.observer.event.DefaultEvent;
import me.zhengjie.observer.type.agv.AgvActionEventType;
import me.zhengjie.service.TaskListService;
import me.zhengjie.service.TrafficCtlAreaService;
import me.zhengjie.utils.Test1;
import net.dreamlu.mica.core.utils.JsonUtil;
import org.slf4j.MDC;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.validation.constraints.NotBlank;
import java.util.List;

@Slf4j
@Api(tags = "test")
//@RequestMapping("/agv")
@RestController
@RequiredArgsConstructor
public class TestController {

    private final RestTemplate restTemplate;

    private final TrafficCtlAreaService trafficCtlAreaService;

    private final TaskListService tasklistService;

    private final IpDto ipDto;

    private final WcsMulticaster wcsMulticaster;

    private final ObjectMapper objectMapper = new ObjectMapper();

    private String getJsonInfo(Object object) {
        String writeValueAsString = null;
        try {
            writeValueAsString = objectMapper.writeValueAsString(object);
        } catch (Exception e) {
            log.error("转成json错误", e);
        }
        return writeValueAsString;
    }

    //申请进入交管区  agvc调用此接口
    @PostMapping("/applyTrafficCtlArea")
    public Result<Object> getApply(@RequestBody TrafficCtlArea t1) {
        //交管区只能让一个agv进去
        //申请进入
        // 查agv编号是否为空  空：能进入 [更新表：写入agv编号 申请信息 1-进入申请]  不为空：不能进入
        if (t1.getType() == 1) {
            //进入申请
            TrafficCtlArea t2 = this.trafficCtlAreaService.selectArea(t1);
            if (t2.getAgvNo() != null)
                return Result.fail();
            //agv编号为空 没有agv 能进入
            boolean r1 = this.trafficCtlAreaService.updateArea(t1);
            return r1 ? Result.ok() : Result.fail();
        }
        //离开告知
        else if (t1.getType() == 2) {
            TrafficCtlArea t3 = new TrafficCtlArea();
            t3.setAreaName(t1.getAreaName());
            t3.setAgvNo("");
            t3.setType(0);
            boolean r2 = this.trafficCtlAreaService.updateArea(t3);
            return r2 ? Result.ok() : Result.fail();
        }
        return Result.fail();
    }

    //发任务  wcs调用agvc接口
    @Transactional(rollbackFor = Exception.class)
    @GetMapping("/sentTask")
    public Result<Object> sentTask(@RequestParam(required = true) String fromPoint,
                                   @RequestParam(required = true) String toPoint,
                                   @RequestParam(required = true) String taskId,
                                   @RequestParam(required = true) String taskType) {
        MDC.put("moduleName", "Agv");
        Tasks tasks = Test1.makeTasks(fromPoint, toPoint, taskId, taskType);
        log.info("发送TUSK任务: {}", getJsonInfo(tasks));

        // 写库 [任务id、任务状态、任务下发时间]   {更新任务状态}
        String st1 = String.join(",", tasks.getTargets());
//        String[] target= new String[2];
//        target[0]=fromPoint;
//        target[1]=toPoint;

        TaskList tasklist = new TaskList();
        tasklist.setTaskId(tasks.getTaskId());
        tasklist.setStatus("-1");
        tasklist.setTargets(st1);

        boolean re = this.tasklistService.insert(tasklist);
        if (!re)
            throw new RuntimeException("执行异常!");

        String url = ipDto.getIpUrl() + "/rpc/createTask";
        ResponseEntity<Result> responseEntity = restTemplate.postForEntity(url, tasks, Result.class);
        // 确认收到任务  return code
        log.info("确认收到TUSK任务 responseEntity = {}", getJsonInfo(responseEntity.getBody()));
        if (responseEntity.getStatusCode() != HttpStatus.OK)
            //return Result.fail();
            throw new RuntimeException("执行异常!");

        MDC.remove("moduleName");

        if (responseEntity.getBody().getCode() != 200) {
            //return Result.fail();
            throw new RuntimeException("执行异常!");
        } else {
            return Result.ok();
        }
    }

    //继续任务  wcs调用agvc接口
    @ApiOperation("continueTask")
    @PostMapping("/continueTask")
    public Result<Object> continueTask(@RequestParam @NotBlank String taskId) {
        //从前端获取任务id[taskId]
        //调用agvc继续任务接口  发送taskId    /test2/testTask
        String url = ipDto.getIpUrl() + "/rpc/continueTask";
        System.out.println("url = " + url);
        ResponseEntity<Result> result = restTemplate.postForEntity(url, taskId, Result.class);
        log.info("result = {}", result);
        if (result.getStatusCode() != HttpStatus.OK)
            return Result.fail();

        if (result.getBody().getCode() != 200)
            return Result.fail();

        return Result.fail();
    }

    //取消  wcs调用agvc接口
    @ApiOperation("cancelTask")
    @RequestMapping("/cancelTask")  //post
    public Result<Object> cancelTask(@RequestParam @NotBlank String taskId) {   //taskId
        //从前端获取任务id[taskId]
        //调用agvc取消任务接口  发送taskId    /test2/testTask
        String url = ipDto.getIpUrl() + "/rpc/cancelTask";
        ResponseEntity<Result> result = restTemplate.postForEntity(url, taskId, Result.class);
        log.info("result = {}", result);
        if (result.getStatusCode() != HttpStatus.OK)
            return Result.fail();

        if (result.getBody().getCode() != 200)
            return Result.fail();

        return Result.fail();
    }

    //任务回调   agvc调用wcs接口   以/feedbackTask结尾
    @ApiOperation("/getTask/feedbackTask")
    @PostMapping("/feedbackTask")
    @Transactional
    public Result<Object> getTask(@RequestBody FeedbackTaskDto dto) {
        MDC.put("moduleName", "Agv");
        try {
            log.info("收到TUSK到达点位信息 {}", objectMapper.writeValueAsString(dto));
        } catch (JsonProcessingException e) {
            log.error("TUSK到达点位信息日志错误", e);
        }

        //agcv的任务回调接口调用此接口
        //wcs接受收信息 [任务Id、agv编号、targetPoint(agv点位)]
        //验证信息是否正确
        log.info("dto = {}", dto);
        TaskList t1 = this.tasklistService.queryTask(dto.getTaskId());
        if (t1 == null) {
            return Result.fail();
        }

        String[] st1 = t1.getTargets().split(",");
        boolean re = true;
        if (dto.getTargetPoint().equals(st1[0])) {
            wcsMulticaster.multicastEvent(DefaultEvent.create(dto), AgvActionEventType.GET);
            //第一个target点 from点
            t1.setStatus("0");
            t1.setAgvNo(dto.getAgvNo());
            re = this.tasklistService.updateTask(t1);
        } else if (dto.getTargetPoint().equals(st1[1])) {
            wcsMulticaster.multicastEvent(DefaultEvent.create(dto), AgvActionEventType.PUT);
            //第二个target点 to点
            t1.setStatus("1");
            t1.setAgvNo(dto.getAgvNo());
            re = this.tasklistService.updateTask(t1);
            tasklistService.deleteByTaskId(t1.getTaskId());
        } else {
            wcsMulticaster.multicastEvent(DefaultEvent.create(dto), AgvActionEventType.PUT_AMEND);
            String st3 = st1[0] + "," + dto.getTargetPoint();
            t1.setTargets(st3);
            t1.setStatus("1");
            re = this.tasklistService.updateTask(t1);
            tasklistService.deleteByTaskId(t1.getTaskId());
        }


        MDC.remove("moduleName");
        return re ? Result.ok() : Result.fail();
    }

    //获取agv异常
    @GetMapping("/getAlarms")
    public Result<AlarmsDto> getAlarms() {
        //调用agvd的getAlarms接口  接收异常信息
        String url = ipDto.getIpUrl() + "/rpc/getAlarms";
        ResponseEntity<Result<List<AlarmsDto>>> result = restTemplate.exchange(url,
                HttpMethod.GET, new HttpEntity<>(new HttpHeaders()),
                new ParameterizedTypeReference<Result<List<AlarmsDto>>>() {
                });
        log.info("result = {}", result);
        if (result.getStatusCode() != HttpStatus.OK)
            return Result.fail();
        if (result.getBody().getCode() != 200)
            return Result.fail();

        Result<List<AlarmsDto>> re = result.getBody();
        List<AlarmsDto> alarmsDtoList = re.getData();
        for (AlarmsDto alarmsDto : alarmsDtoList) {
            log.info("agv异常信息  alarmsDto = {}", alarmsDto);
        }


        return Result.ok();
    }

    //获取agv状态 wcs调用agvc接口
    @GetMapping("/getAgv")
    public Result<RobotDto> getAgv() {
        //获取agv状态 wcs调用agvc接口
        String url = ipDto.getIpUrl() + "/rpc/getOnlineRobot";
        ResponseEntity<Result<List<RobotDto>>> result = restTemplate.exchange(url,
                HttpMethod.GET, new HttpEntity<>(new HttpHeaders()),
                new ParameterizedTypeReference<Result<List<RobotDto>>>() {
                });
        log.info("result = {}", result);
        if (result.getStatusCode() != HttpStatus.OK)
            return Result.fail();
        if (result.getBody().getCode() != 200)
            return Result.fail();

        Result<List<RobotDto>> re = result.getBody();
        List<RobotDto> robotDtoList = re.getData();
        for (RobotDto robotDto : robotDtoList) {
            log.info("agv状态信息  robotDto = {}", robotDto);
        }
        return Result.ok();
    }

    //地图
    @GetMapping("/getMap")
    public Result<Object> getMap(@RequestParam Integer mapId) {
        //调用agvc接口获取地图  给mapId  /rpc
        String url = ipDto.getIpUrl() + "/getMapInfo?mapId={mapId}";
        ResponseEntity<Result<List<MapDto>>> result = restTemplate.exchange(url,
                HttpMethod.GET, new HttpEntity<>(new HttpHeaders()),
                new ParameterizedTypeReference<Result<List<MapDto>>>() {
                }, mapId);
        log.info("result = {}", result);
        if (result.getStatusCode() != HttpStatus.OK)
            return Result.fail();
        if (result.getBody().getCode() != 200)
            return Result.fail();

        Result<List<MapDto>> re = result.getBody();
        List<MapDto> mapDtoList = re.getData();
        for (MapDto mapDto : mapDtoList) {
            log.info("地图信息  mapDto = {}", mapDto);
        }


        return Result.ok();
    }
}
